<template>
	<section class="m-calendar" :style="dateStyle">
		<!-- 切换月份 -->
		<header class="changeMonth">
			<span class="prepMonth" @click="changeMonth(-1)"></span>
			<h1>{{ year }}年{{ month }}月</h1>
			<span class="nextMonth" @click="changeMonth(1)"></span>
		</header>
		<ul class="dates">
			<!-- 星期 -->
			<li class="weeks" v-for="item in weeks" :key="item">{{ item }}</li>
			<!-- 日期 -->
			<el-divider style="margin:0"></el-divider>
			<li
				class="day"
				v-for="(item, i) in dates"
				:key="i"
				:class="{
					isPrep: item.isPrep,
					isNext: item.isNext,
					hidden: (item.isNext || item.isPrep) && !showPrepNext,
					isToday: item.date == today,
					isSelected: item.date == selectedDate,
					isMarked: markDates.includes(item.date)
				}"
				@click="clickDate(item)"
			>
				<!-- {{ item.date == today ? '今' : item.day }} -->
				{{ item.day }}
			</li>
		</ul>
	</section>
</template>

<script>
const D = new Date()
const ThisYear = D.getFullYear()
const ThisMonth = D.getMonth() + 1
const today = new Date().toLocaleDateString()
export default {
	// props都为非必传
	props: {
		// 初始年月
		startYearMonth: {
			type: String,
			default() {
				return `${ThisYear}/${ThisMonth}`
				// 格式：2021-1或2020-01或者2020/1或者2020/01
			}
		},
		// 需要标记的日期数组
		markDate: {
			type: Array,
			default() {
				return []
				// 格式：['2020-01-01', '2020-02-12']
			}
		},
		// 选中的日期
		checkedDate: {
			type: String,
			default() {
				return ''
				// 格式：'2020-01-01'
			}
		},
		// 是否星期一开始，默认星期一开始
		mondayStart: {
			type: Boolean,
			default() {
				return true
			}
		},
		// 是否显示上个月和下个月日期
		showPrepNext: {
			type: Boolean,
			default() {
				return true
			}
		},
		// 日期字体颜色
		fontColor: {
			type: String,
			default() {
				return '#000'
			}
		},
		// 标记点颜色
		markColor: {
			type: String,
			default() {
				return '#ff6633'
			}
		},
		// 选中的日期字体颜色
		activeColor: {
			type: String,
			default() {
				return '#fff'
			}
		},
		// 选中的日期背景颜色
		activeBgColor: {
			type: String,
			default() {
				return '#ff6633'
			}
		}
	},
	data() {
		return {
			// 当前年
			year: ThisYear,
			// 当前月
			month: ThisMonth,
			// 今天
			today,
			// 日期数组
			dates: [],
			// 选中的日期
			selectedDate: ''
		}
	},
	computed: {
		// 标记的日期
		markDates() {
			// 获得不带0的日期，如：2021/1/1  =>  2021/1/1
			return this.markDate.map(item => this.formatDate(item))
		},
		// 星期
		weeks() {
			if (this.mondayStart) {
				return ['一', '二', '三', '四', '五', '六', '日']
			} else {
				return ['日', '一', '二', '三', '四', '五', '六']
			}
		},
		dateStyle() {
			return {
				'--font-color': this.fontColor,
				'--mark-color': this.markColor,
				'--active-color': this.activeColor,
				'--active-bg-color': this.activeBgColor
			}
		}
	},
	created() {
		this.year = new Date(this.startYearMonth).getFullYear()
		this.month = new Date(this.startYearMonth).getMonth() + 1
		// 选中的日期
		if (this.checkedDate) {
			// 获得不带0的日期，如：2021-1-1  =>  2021/1/1
			this.selectedDate = this.formatDate(this.checkedDate)
		}
		// 初始化日历
		this.initCalendar()
	},
	methods: {
		// 初始化日历
		initCalendar() {
			// ⚠️注意：new Date中的month要减1才是真正的本月月数，即本月：this.month - 1，下个月：this.month
			// ⚠️注意：下个月的第0天即为本月的最后一天
			// 上个月总天数（本月第0天日期）
			const prepMonthDays = new Date(this.year, this.month - 1, 0).getDate()
			// 上个月最后一天星期几（本月第0天星期数）
			const prepMonthEndDayWeek = new Date(this.year, this.month - 1, 0).getDay()
			// 当前月总天数（下个月第0天日期）
			const thisMonthDays = new Date(this.year, this.month, 0).getDate()
			// 当前月第一天是星期几
			const firstDayWeek = new Date(this.year, this.month - 1, 1).getDay()
			// 当前月最后一天是星期几（下个月第0天星期数）
			const thisEndDayWeek = new Date(this.year, this.month, 0).getDay()
			var dates = []
			// 需要计算的总天数
			var totalDays = firstDayWeek + thisMonthDays
			// 从星期一开始index为1，从星期天开始index为0
			var index = this.mondayStart ? 1 : 0
			// 星期一开始且本月最后一天是星期天之后，需补满最后一行
			if (this.mondayStart && thisEndDayWeek > 0) {
				totalDays += 7 - thisEndDayWeek
			} else if (!this.mondayStart && thisEndDayWeek < 6) {
				// 星期天开始且本月最后一天是星期天之前，需补满最后一行
				totalDays += 6 - thisEndDayWeek
			}
			for (index; index < totalDays; index++) {
				// 上个月月底
				if (index < firstDayWeek) {
					// 上个月天数 - 上个月最后一天星期数 + 下标 (如：31 - 5 + 0)
					const day = prepMonthDays - prepMonthEndDayWeek + index
					const date = new Date(this.year, this.month - 2, day).toLocaleDateString()
					dates.push({ isPrep: true, day, date })
				} else if (index >= firstDayWeek + thisMonthDays) {
					// 下个月月初
					// 下标 - 当前月总天数 - 当前月第一天星期数 + 1 (如：30 - 31 + 1 + 1)
					const day = index - thisMonthDays - firstDayWeek + 1
					const date = new Date(this.year, this.month, day).toLocaleDateString()
					dates.push({ isNext: true, day, date })
				} else {
					// 本月
					// 下标 - 当前月第一天星期数 + 1 (如：5 - 5 + 1)
					const day = index - firstDayWeek + 1
					const date = new Date(this.year, this.month - 1, day).toLocaleDateString()
					dates.push({ day, date })
				}
			}
			this.dates = [...dates]
		},
		// 点击日期
		clickDate({ date, isPrep, isNext }) {
			if (isPrep || isNext) return
			this.selectedDate = date
			this.$emit('clickDate', date.replace(/\//g, '-'))
		},
		// 切换月份
		changeMonth(month) {
			this.month += month
			if (this.month === 0) {
				this.month = 12
				this.year--
			} else if (this.month === 13) {
				this.month = 1
				this.year++
			}
			this.initCalendar()
			this.$emit('changeMonth', `${this.year}-${this.month}`)
		},
		// 格式化日期
		formatDate(date) {
			// 获得不带0，且分隔符为/的日期，如：2020-01-01  =>  2021/1/1
			return new Date(date).toLocaleDateString()
		}
	}
}
</script>

<style lang="scss" scoped>
$fontColor: var(--font-color);
$markColor: var(--mark-color);
$activeColor: var(--active-color);
$activeBgColor: var(--active-bg-color);
.m-calendar {
	max-width: 400px;
	max-height: 450px;
	border: 1px solid #ffffff;
	border-radius: 8px 8px 0 0;
	// padding-bottom: 20px;
	header {
		display: flex;
		align-items: center;
		justify-content: left;
		border-bottom: 1px solid #ffffff;
		padding: 10px 0;
		margin-bottom: 5px;
		height: 14px;
		h1 {
			margin: 0 8px;
			color: rgba(0, 0, 0, 0.4);
			font-size: 14px;
			font-weight: bold;
			width: 75px;
			text-align: center;
		}
		span {
			cursor: pointer;
			padding: 4px 10px;
			&::after {
				display: inline-block;
				content: '';
				width: 7px;
				height: 7px;
				border-top: 1px solid rgba(0, 0, 0, 0.4);
			}
			&.prepMonth::after {
				border-left: 1px solid rgba(0, 0, 0, 0.4);
				transform: rotate(-45deg);
			}
			&.nextMonth::after {
				border-right: 1px solid rgba(0, 0, 0, 0.4);
				transform: rotate(45deg);
			}
			&:hover::after {
				border-color: $markColor;
			}
		}
	}
	ul {
		display: flex;
		flex-wrap: wrap;
		margin: 0 auto;
		padding: 0;
		li {
			width: 42px;
			height: 42px;
			margin: 4px calc((100% / 7 - 42px) / 2);
			display: flex;
			flex-direction: column;
			justify-content: center;
			align-items: center;
			font-weight: bold;
			position: relative;
			transition: all ease 0.25s;
			border-radius: 6px;
			// 标记
			&::after {
				bottom: 0;
				left: 50%;
				transform: translateX(-50%);
				position: absolute;
				display: inline-block;
				content: '';
				width: 5px;
				height: 5px;
				border-radius: 50%;
			}
			// 星期
			&.weeks {
				font-size: 14px;
				color: rgba(68, 68, 68, 0.4);
				margin-bottom: 12px;
			}
			&.day {
				cursor: pointer;
				font-size: 14px;
				color: $fontColor;
				// 今天
				&.isToday {
					color: $markColor;
				}
				// 标记
				&.isMarked::after {
					transition: all ease 0.25s;
					background: $markColor;
				}
				// 选中、hover
				&:hover,
				&.isSelected {
					background: $activeBgColor;
					color: $activeColor;
					
					border-radius: 21px;
					&:after {
						display: none;
					}
				}
				// 上个月、下个月
				&.isNext,
				&.isPrep {
					cursor: default;
					opacity: 0;
					&:hover {
						color: $fontColor;
						opacity: 0.3;
						background: transparent;
					}
				}
				// hidden
				&.hidden {
					opacity: 0;
					&:hover {
						opacity: 0;
					}
				}
			}
		}
	}
}
</style>
